package com.zzj.ecology.framework.configuration.security.handler;

import com.alibaba.fastjson.JSON;
import com.zzj.ecology.common.constant.Constant;
import com.zzj.ecology.common.enums.LoginResultEnum;
import com.zzj.ecology.common.utils.MessageUtils;
import com.zzj.ecology.framework.exception.CaptchaException;
import com.zzj.ecology.framework.manager.AsyncManager;
import com.zzj.ecology.framework.manager.async.AsyncTaskFactory;
import com.zzj.ecology.framework.utils.SecurityUtils;
import com.zzj.ecology.system.dto.HttpResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @ClassName CustomizeAuthenticationFailureHandler
 * @Description 登录失败处理逻辑
 * @Author zhijun zeng at 2020/2/28
 * @Version 1.0
 **/
@Component
public class CustomizeAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Autowired
    private AsyncTaskFactory asyncTaskFactory;

    @Autowired
    private AsyncManager asyncManager;


    @Override
    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {

        String username = SecurityUtils.getUsername();
        if (StringUtils.isEmpty(username)) {//如果从认证用户中找不到username，则从登录参数中获取尝试登录的用户名
            username = req.getParameter("username");
        }
        HttpResult result = null;
        // 捕获认证失败的异常
        if (e instanceof CaptchaException) {// 验证码错误
            result = new HttpResult(LoginResultEnum.USER_VERIFY_ERROR);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.jcaptcha.error")));
        }else if (e instanceof AccountExpiredException) {//账号过期
            result = new HttpResult(LoginResultEnum.USER_ACCOUNT_EXPIRED);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.account.expired")));
        } else if (e instanceof BadCredentialsException) {//密码错误
            result = new HttpResult(LoginResultEnum.USER_CREDENTIALS_ERROR);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.password.not.match")));
        } else if (e instanceof CredentialsExpiredException) {//密码过期
            result = new HttpResult(LoginResultEnum.USER_CREDENTIALS_EXPIRED);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.password.expired")));
        } else if (e instanceof DisabledException) {//账号不可用
            result = new HttpResult(LoginResultEnum.USER_ACCOUNT_DISABLE);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.account.disable")));
        } else if (e instanceof LockedException) {//账号锁定
            result = new HttpResult(LoginResultEnum.USER_ACCOUNT_LOCKED);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.account.locked")));
        } else if (e instanceof InternalAuthenticationServiceException) {// UserDetailsService 中捕获的 异常
            //用户不存在
            result = new HttpResult(LoginResultEnum.USER_ACCOUNT_NOT_EXIST);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.not.exists")));
        } else {//其他错误
            result = new HttpResult(LoginResultEnum.UNKNOWN_FAILURE);
            asyncManager.execute(asyncTaskFactory.recordLoginInfor(username, Constant.LOGIN_FAIL, new Date(), MessageUtils.message("user.unknown.error")));
        }

        resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        resp.getWriter().write(JSON.toJSONString(result));//返回错误
    }
}
